]> git.openstreetmap.org Git - rails.git/blobdiff - vendor/plugins/rails-i18n/tools/Rails I18n.tmbundle/Support/lib/dictionary.rb
First stage of i18n. Some migrations and extra plugins.
[rails.git] / vendor / plugins / rails-i18n / tools / Rails I18n.tmbundle / Support / lib / dictionary.rb
diff --git a/vendor/plugins/rails-i18n/tools/Rails I18n.tmbundle/Support/lib/dictionary.rb b/vendor/plugins/rails-i18n/tools/Rails I18n.tmbundle/Support/lib/dictionary.rb
new file mode 100644 (file)
index 0000000..35470eb
--- /dev/null
@@ -0,0 +1,478 @@
+# = Dictionary
+#
+# The Dictionary class is a Hash that preserves order.
+# So it has some array-like extensions also. By defualt
+# a Dictionary object preserves insertion order, but any
+# order can be specified including alphabetical key order.
+#
+# == Usage
+#
+# Just require this file and use Dictionary instead of Hash.
+#
+#   # You can do simply
+#   hsh = Dictionary.new
+#   hsh['z'] = 1
+#   hsh['a'] = 2
+#   hsh['c'] = 3
+#   p hsh.keys     #=> ['z','a','c']
+#
+#   # or using Dictionary[] method
+#   hsh = Dictionary['z', 1, 'a', 2, 'c', 3]
+#   p hsh.keys     #=> ['z','a','c']
+#
+#   # but this don't preserve order
+#   hsh = Dictionary['z'=>1, 'a'=>2, 'c'=>3]
+#   p hsh.keys     #=> ['a','c','z']
+#
+#   # Dictionary has useful extensions: push, pop and unshift
+#   p hsh.push('to_end', 15)       #=> true, key added
+#   p hsh.push('to_end', 30)       #=> false, already - nothing happen
+#   p hsh.unshift('to_begin', 50)  #=> true, key added
+#   p hsh.unshift('to_begin', 60)  #=> false, already - nothing happen
+#   p hsh.keys                     #=> ["to_begin", "a", "c", "z", "to_end"]
+#   p hsh.pop                      #=> ["to_end", 15], if nothing remains, return nil
+#   p hsh.keys                     #=> ["to_begin", "a", "c", "z"]
+#   p hsh.shift                    #=> ["to_begin", 30], if nothing remains, return nil
+#
+# == Usage Notes
+#
+# * You can use #order_by to set internal sort order.
+# * #<< takes a two element [k,v] array and inserts.
+# * Use ::auto which creates Dictionay sub-entries as needed.
+# * And ::alpha which creates a new Dictionary sorted by key.
+#
+# == Authors
+#
+# * Jan Molic
+# * Thomas Sawyer
+#
+# == Acknowledgments
+#
+# * Andrew Johnson (merge, to_a, inspect, shift and Hash[])
+# * Jeff Sharpe    (reverse and reverse!)
+# * Thomas Leitner (has_key? and key?)
+#
+# Originally ported from OrderHash 2.0, Copyright (c) 2005 jan molic
+#
+# == History
+#
+# * 2007.10.31 trans
+# ** Fixed initialize so the constructor blocks correctly effected dictionary rather then just the internal hash.
+#
+# == Copying
+#
+# Copyright (c) 2005 Jan Molic, Thomas Sawyer
+#
+# Ruby License
+#
+# This module is free software. You may use, modify, and/or redistribute this
+# software under the same terms as Ruby.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE.
+
+
+# = Dictionary
+#
+# The Dictionary class is a Hash that preserves order.
+# So it has some array-like extensions also. By defualt
+# a Dictionary object preserves insertion order, but any
+# order can be specified including alphabetical key order.
+#
+# == Usage
+#
+# Just require this file and use Dictionary instead of Hash.
+#
+#   # You can do simply
+#   hsh = Dictionary.new
+#   hsh['z'] = 1
+#   hsh['a'] = 2
+#   hsh['c'] = 3
+#   p hsh.keys     #=> ['z','a','c']
+#
+#   # or using Dictionary[] method
+#   hsh = Dictionary['z', 1, 'a', 2, 'c', 3]
+#   p hsh.keys     #=> ['z','a','c']
+#
+#   # but this don't preserve order
+#   hsh = Dictionary['z'=>1, 'a'=>2, 'c'=>3]
+#   p hsh.keys     #=> ['a','c','z']
+#
+#   # Dictionary has useful extensions: push, pop and unshift
+#   p hsh.push('to_end', 15)       #=> true, key added
+#   p hsh.push('to_end', 30)       #=> false, already - nothing happen
+#   p hsh.unshift('to_begin', 50)  #=> true, key added
+#   p hsh.unshift('to_begin', 60)  #=> false, already - nothing happen
+#   p hsh.keys                     #=> ["to_begin", "a", "c", "z", "to_end"]
+#   p hsh.pop                      #=> ["to_end", 15], if nothing remains, return nil
+#   p hsh.keys                     #=> ["to_begin", "a", "c", "z"]
+#   p hsh.shift                    #=> ["to_begin", 30], if nothing remains, return nil
+#
+# == Usage Notes
+#
+# * You can use #order_by to set internal sort order.
+# * #<< takes a two element [k,v] array and inserts.
+# * Use ::auto which creates Dictionay sub-entries as needed.
+# * And ::alpha which creates a new Dictionary sorted by key.
+#
+class Dictionary
+
+  include Enumerable
+
+  class << self
+    #--
+    # TODO is this needed? Doesn't the super class do this?
+    #++
+
+    def [](*args)
+      hsh = new
+      if Hash === args[0]
+        hsh.replace(args[0])
+      elsif (args.size % 2) != 0
+        raise ArgumentError, "odd number of elements for Hash"
+      else
+        while !args.empty?
+          hsh[args.shift] = args.shift
+        end
+      end
+      hsh
+    end
+
+    # Like #new but the block sets the order.
+    #
+    def new_by(*args, &blk)
+      new(*args).order_by(&blk)
+    end
+
+    # Alternate to #new which creates a dictionary sorted by key.
+    #
+    #   d = Dictionary.alpha
+    #   d["z"] = 1
+    #   d["y"] = 2
+    #   d["x"] = 3
+    #   d  #=> {"x"=>3,"y"=>2,"z"=>2}
+    #
+    # This is equivalent to:
+    #
+    #   Dictionary.new.order_by { |key,value| key }
+
+    def alpha(*args, &block)
+      new(*args, &block).order_by_key
+    end
+
+    # Alternate to #new which auto-creates sub-dictionaries as needed.
+    #
+    #   d = Dictionary.auto
+    #   d["a"]["b"]["c"] = "abc"  #=> { "a"=>{"b"=>{"c"=>"abc"}}}
+    #
+    def auto(*args)
+      #AutoDictionary.new(*args)
+      leet = lambda { |hsh, key| hsh[key] = new(&leet) }
+      new(*args, &leet)
+    end
+  end
+
+   # New Dictiionary.
+
+  def initialize(*args, &blk)
+    @order = []
+    @order_by = nil
+    if blk
+      dict = self                                  # This ensure autmatic key entry effect the
+      oblk = lambda{ |hsh, key| blk[dict,key] }    # dictionary rather then just the interal hash.
+      @hash = Hash.new(*args, &oblk)
+    else
+      @hash = Hash.new(*args)
+    end
+  end
+
+  def order
+    reorder if @order_by
+    @order
+  end
+
+  # Keep dictionary sorted by a specific sort order.
+
+  def order_by( &block )
+    @order_by = block
+    order
+    self
+  end
+
+  # Keep dictionary sorted by key.
+  #
+  #   d = Dictionary.new.order_by_key
+  #   d["z"] = 1
+  #   d["y"] = 2
+  #   d["x"] = 3
+  #   d  #=> {"x"=>3,"y"=>2,"z"=>2}
+  #
+  # This is equivalent to:
+  #
+  #   Dictionary.new.order_by { |key,value| key }
+  #
+  # The initializer Dictionary#alpha also provides this.
+
+  def order_by_key
+    @order_by = lambda { |k,v| k }
+    order
+    self
+  end
+
+  # Keep dictionary sorted by value.
+  #
+  #   d = Dictionary.new.order_by_value
+  #   d["z"] = 1
+  #   d["y"] = 2
+  #   d["x"] = 3
+  #   d  #=> {"x"=>3,"y"=>2,"z"=>2}
+  #
+  # This is equivalent to:
+  #
+  #   Dictionary.new.order_by { |key,value| value }
+
+  def order_by_value
+    @order_by = lambda { |k,v| v }
+    order
+    self
+  end
+
+  #
+
+  def reorder
+    if @order_by
+      assoc = @order.collect{ |k| [k,@hash[k]] }.sort_by(&@order_by)
+      @order = assoc.collect{ |k,v| k }
+    end
+    @order
+  end
+
+  #def ==( hsh2 )
+  #  return false if @order != hsh2.order
+  #  super hsh2
+  #end
+
+  def ==(hsh2)
+    if hsh2.is_a?( Dictionary )
+      @order == hsh2.order &&
+      @hash  == hsh2.instance_variable_get("@hash")
+    else
+      false
+    end
+  end
+
+  def [] k
+    @hash[ k ]
+  end
+
+  def fetch(k, *a, &b)
+    @hash.fetch(k, *a, &b)
+  end
+
+  # Store operator.
+  #
+  #   h[key] = value
+  #
+  # Or with additional index.
+  #
+  #  h[key,index] = value
+
+  def []=(k, i=nil, v=nil)
+    if v
+      insert(i,k,v)
+    else
+      store(k,i)
+    end
+  end
+
+  def insert( i,k,v )
+    @order.insert( i,k )
+    @hash.store( k,v )
+  end
+
+  def store( a,b )
+    @order.push( a ) unless @hash.has_key?( a )
+    @hash.store( a,b )
+  end
+
+  def clear
+    @order = []
+    @hash.clear
+  end
+
+  def delete( key )
+    @order.delete( key )
+    @hash.delete( key )
+  end
+
+  def each_key
+    order.each { |k| yield( k ) }
+    self
+  end
+
+  def each_value
+    order.each { |k| yield( @hash[k] ) }
+    self
+  end
+
+  def each
+    order.each { |k| yield( k,@hash[k] ) }
+    self
+  end
+  alias each_pair each
+
+  def delete_if
+    order.clone.each { |k| delete k if yield(k,@hash[k]) }
+    self
+  end
+
+  def values
+    ary = []
+    order.each { |k| ary.push @hash[k] }
+    ary
+  end
+
+  def keys
+    order
+  end
+
+  def invert
+    hsh2 = self.class.new
+    order.each { |k| hsh2[@hash[k]] = k }
+    hsh2
+  end
+
+  def reject(&block)
+    self.dup.delete_if(&block)
+  end
+
+  def reject!( &block )
+    hsh2 = reject(&block)
+    self == hsh2 ? nil : hsh2
+  end
+
+  def replace( hsh2 )
+    @order = hsh2.order
+    @hash = hsh2.hash
+  end
+
+  def shift
+    key = order.first
+    key ? [key,delete(key)] : super
+  end
+
+  def unshift( k,v )
+    unless @hash.include?( k )
+      @order.unshift( k )
+      @hash.store( k,v )
+      true
+    else
+      false
+    end
+  end
+
+  def <<(kv)
+    push(*kv)
+  end
+
+  def push( k,v )
+    unless @hash.include?( k )
+      @order.push( k )
+      @hash.store( k,v )
+      true
+    else
+      false
+    end
+  end
+
+  def pop
+    key = order.last
+    key ? [key,delete(key)] : nil
+  end
+
+  def inspect
+    ary = []
+    each {|k,v| ary << k.inspect + "=>" + v.inspect}
+    '{' + ary.join(", ") + '}'
+  end
+
+  def dup
+    a = []
+    each{ |k,v| a << k; a << v }
+    self.class[*a]
+  end
+
+  def update( hsh2 )
+    hsh2.each { |k,v| self[k] = v }
+    reorder
+    self
+  end
+  alias :merge! update
+
+  def merge( hsh2 )
+    self.dup.update(hsh2)
+  end
+
+  def select
+    ary = []
+    each { |k,v| ary << [k,v] if yield k,v }
+    ary
+  end
+
+  def reverse!
+    @order.reverse!
+    self
+  end
+
+  def reverse
+    dup.reverse!
+  end
+
+  #
+  def first(x=nil)
+    return @hash[order.first] unless x
+    order.first(x).collect { |k| @hash[k] }
+  end
+
+  #
+  def last(x=nil)
+    return @hash[order.last] unless x
+    order.last(x).collect { |k| @hash[k] }
+  end
+
+  def length
+    @order.length
+  end
+  alias :size :length
+
+  def empty?
+    @hash.empty?
+  end
+
+  def has_key?(key)
+    @hash.has_key?(key)
+  end
+
+  def key?(key)
+    @hash.key?(key)
+  end
+
+  def to_a
+    ary = []
+    each { |k,v| ary << [k,v] }
+    ary
+  end
+
+  def to_s
+    self.to_a.to_s
+  end
+
+  def to_hash
+    @hash.dup
+  end
+
+  def to_h
+    @hash.dup
+  end
+end
\ No newline at end of file